<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>easy_ngx_waf 摘要报告</title>
    <!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous"> -->
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.6.2/css/bootstrap.min.css" />
  </head>
  <body>
    <style>
      html,
      body {
        font-size: 16px;
      }
      body {
        background-image: url("");
        background-position-x: left;
        background-position-y: top;
        background-repeat: repeat;
      }
      p,
      div {
        padding: 0;
        margin: 0;
      }
      .fs-0 {
        font-size: 0 !important;
      }
      .fs-14 {
        font-size: 14px !important;
      }
      ::selection {
        background-color: #007bff;
        color: #f8f9fa;
      }
      .blockquote {
        font-size: 1rem;
        margin: 8px 0;
        padding: 8px 1rem;
        line-height: 1.2;
        border-left-style: solid;
        border-left-color: #cdcdcd;
        color: #555555;
        /* color: var(--secondary); */
        border-left-width: 3px;
      }
      .blockquote p,
      .blockquote div {
        margin-bottom: 8px;
      }
      .blockquote p:last-child,
      .blockquote div:last-child {
        margin-bottom: 0;
      }
      .title {
        padding: 8px 18px;
        border-left: 3px solid #007bff;
        border-left-color: var(--primary);
      }
      .title-sub {
        position: relative;
        padding: 8px 0.6em 4px;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        line-height: 1.2;
        box-sizing: border-box;
        color: #007bff;
        color: var(--pink);
      }
      .title-sub::before {
        content: "";
        display: block;
        position: absolute;
        top: 50%;
        left: 0;
        transform: translateY(-50%);

        width: 4px;
        height: 4px;
        border-radius: 4px;
        background-color: #007bff;
        background-color: var(--pink);
      }
      .result-wrap {
        font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
        position: relative;
        display: flex;
        flex-wrap: nowrap;
        align-items: stretch;
        margin-bottom: 0.5rem;
        max-width: 100%;
      }
      .result-wrap .prepend,
      .result-wrap .result {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-grow: 0;
        flex-shrink: 0;
        padding: 1px 1em;
        font-weight: 400;
        line-height: 1.2;
      }
      .result-wrap .prepend {
        margin-right: -1px;
        border: 1px solid #ced4da;
        border-radius: 4px;
        border-top-right-radius: 0;
        border-bottom-right-radius: 0;
        font-size: 0.875em;
        color: #e83e8c;
        color: var(--pink);
        border-color: var(--purple);
      }
      .result-wrap .result {
        position: relative;
        min-width: 0;
        font-size: 1em;
        color: #495057;
        background-color: #fff;
        background-clip: padding-box;
        border: 1px solid #ced4da;
        border-radius: 4px;
        color: #555555;
        background-color: #f8f9fa;
        color: var(--light);
        background-color: var(--purple);
        border-color: var(--purple);
        word-break: break-all;
      }
      .result-wrap .result::before {
        content: " ";
        display: flex;
        justify-content: center;
        align-items: center;
        position: absolute;
        top: 50%;
        left: -1px;
        transform: translateY(-50%);

        width: 0;
        height: 0;
        border-left: 0.4em solid #fff;
        border-top: 0.4em solid transparent;
        border-bottom: 0.4em solid transparent;
      }
      /* .result-wrap .result::after{
        content: "value";
        font-size: 10px;
        color: #ddd;
        line-height: 1;
        display: flex;
        justify-content: center;
        align-items: center;
        position: absolute;
        padding: 0 3px;
        box-sizing: border-box;
        top: -1px;
        right: 0;
        transform: scale(80%) translateX(10%);
      } */
      .result-wrap .prepend + .result {
        border-top-left-radius: 0;
        border-bottom-left-radius: 0;
        flex-shrink: 2;
      }
      @media screen and (max-width: 767.98px) {
        .result-wrap .prepend {
          flex-shrink: 1;
          word-break: break-all;
          /* word-break: break-word; */
        }
        .result-wrap .prepend,
        .result-wrap .result {
          padding-left: 0.5em;
          padding-left: 0.5em;
        }
      }
      .table .col-name {
        text-align: center;
        vertical-align: middle;
        width: 45%;
        color: #007bff;
        color: var(--pink);
      }
      .table .col-value {
        vertical-align: middle;
        padding-left: 12px;
        color: #007bff;
        color: var(--primary);
      }
      .table .col-pink {
        vertical-align: middle;
        padding-left: 12px;
        color: #e83e8c;
        color: var(--pink);
      }

      .table .desc {
        font-size: 12px;
        color: #aaa;
        color: var(--gray);
        user-select: none;
      }
      .btn:active,
      .btn:focus {
        box-shadow: none;
        outline: none;
      }
      .btn::-moz-focus-inner {
        border: none;
      }
      .footer {
        min-height: 30px;
        font-size: 14px;
        background-color: rgb(10, 10, 10,.9);
        color: var(--white);
      }
      .footer p{
        display: inline-block;
        align-self: center;
      }
    </style>
    <div class="container-lg my-5">
      <div class="card p-md-3 my-3 shadow">
        <div class="card-body">
          <h2 class="text-primary card-title mb-3 mb-md-4">easy_ngx_waf 配置概要</h2>

          <blockquote class="blockquote mx-md-3">
            <div>
              <span class="mr-4">nginx 版本： <code><%- nginx_version %></code></span>
              <span class="mr-5">LUA 版本： <code><%- lua_version %></code></span>
            </div>

            <p>配置文件： <code><%- config.waf_base_path %><%- package.config:sub(1,1) %>config.lua</code></p>
            <div>
              WAF日志文件：
              <div class="d-inline-block">
                <p class="result-wrap">
                  <span class="prepend">config.waf_log_file</span>
                  <span class="result"><%- config.waf_log_file %></span>
                </p>
              </div>
            </div>
          </blockquote>

          <div class="card-text">
            <h5 class="title-sub">校验开关</h5>
            <div class="row mx-md-3 mt-3">
              <div class="col-md-5 col-12">
                <table class="table table-bordered table-sm">
                  <tbody>
                    <tr>
                      <td class="col-name w-75 text-monospace">WAF总开关</td>
                      <% if util.check_switch_is_on(config.waf_enable) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">WAF日志开关</td>
                      <% if util.check_switch_is_on(config.waf_log) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">IP白名单校验</td>
                      <% if util.check_switch_is_on(config.ip_white_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">IP黑名单校验</td>
                      <% if util.check_switch_is_on(config.ip_black_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">UA白名单校验</td>
                      <% if util.check_switch_is_on(config.user_agent_white_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">UA校验</td>
                      <% if util.check_switch_is_on(config.user_agent_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">URL白名单校验</td>
                      <% if util.check_switch_is_on(config.url_white_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">URL校验</td>
                      <% if util.check_switch_is_on(config.url_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">SEO蜘蛛校验</td>
                      <% if util.check_switch_is_on(config.seo_spider_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">境外IP禁止访问校验</td>
                      <% if util.check_switch_is_on(config.ip_foreign_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">CC校验</td>
                      <% if util.check_switch_is_on(config.cc_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">COOKIE校验</td>
                      <% if util.check_switch_is_on(config.cookie_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">ARGS参数校验</td>
                      <% if util.check_switch_is_on(config.args_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                    <tr>
                      <td class="col-name text-monospace">POST参数校验</td>
                      <% if util.check_switch_is_on(config.post_check) then %>
                      <td class="col-value text-monospace">on</td>
                      <% else %>
                      <td class="col-pink text-monospace">off</td>
                      <% end %>
                    </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </div>

          <div class="card-text">
            <h5 class="title-sub">排除域名列表</h5>
            <div class="mx-3">
              <blockquote class="blockquote">
                <p>不参与WAF检测的域名(可设置全局排除，也可针对各检测阶段设置排除域名；可针对具体域名设置，也可设置通配符域名；)</p>
                <div>
                  配置方法：
                  <div class="d-inline-block">
                    <p class="result-wrap">
                      <span class="prepend">config.host_x</span>
                      <span class="result">{all={"www.a.com","*.b.com"}, ip_white={...}, args={...}, ...}</span>
                    </p>
                  </div>
                </div>
                <!-- 设置有 easy_waf_cc_dict,展示信息 -->
                <p class="text-muted">排除域名设置注意事项</p>
                <p class="text-muted">&ensp;&ensp;&ensp;1.排除域名为具体域名 如: "<code>abc.com</code>"，只针对 "<code>abc.com</code>" 域名排除，"<code>www.abc.com</code>" 还是参与waf检测的；</p>
                <p class="text-muted">&ensp;&ensp;&ensp;2.排除域名为通配符域名 如: "<code>*.abc.com</code>"，针对所有 "<code>abc.com</code>" 域名 ("<code>abc.com</code>"、"<code>www.abc.com</code>"、"<code>x.y.abc.com</code>" ... ) 都排除；</p>

                <div class="row">
                  <div class="col-md-10 col-12">
                    <table class="table table-bordered table-sm">
                      <thead class="">
                        <tr>
                          <th class="text-center">config.host_x 排除配置项</th>
                          <th class="text-center">排除域名</th>
                        </tr>
                      </thead>
                      <tbody>
                        <tr>
                          <td class="col-name text-monospace">"all" (全局排除)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.all) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"ip_white" (IP白名单检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.ip_white) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"ip_black" (IP黑名单检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.ip_black) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"ip_foreign" (境外IP检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.ip_foreign) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"ua" (user-agent检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.ua) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"cookie" (cookie检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.cookie) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"cc" (CC检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.cc) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"args" (get检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.args) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                        <tr>
                          <td class="col-name text-monospace">"post" (post检测阶段)</td>
                          <td class="col-value fs-0">
                            <% for _, h in ipairs(config.host_x.post) do %>
                            <span class="badge badge-warning text-monospace mr-1 mb-1 fs-14"><%- h %></span>
                            <% end %>
                          </td>
                        </tr>
                      </tbody>
                    </table>
                  </div>
                </div>
              </blockquote>
            </div>
          </div>
        </div>
      </div>

      <div class="card p-md-3 my-3 shadow">
        <div class="card-body">
          <h2 class="text-primary card-title mb-3 mb-md-4">WAF公共缓存</h2>

          <div class="card-text">
            <h5 class="title-sub">easy_waf_cache</h5>
            <div class="mx-3">
              <blockquote class="blockquote">
                <p>WAF公共缓存共享内存(不同变量用各自前缀避免变量名冲突)。例如：保存排除域名数组等。</p>
                <div>
                  配置方法：<code>nginx.conf http段</code> 添加
                  <div class="d-inline-block">
                    <p class="result-wrap">
                      <span class="prepend">lua_shared_dict</span>
                      <span class="result">easy_waf_cache ?m;</span>
                    </p>
                  </div>
                </div>
                <% if not easy_waf_cache then %>
                <!-- 未设置 easy_waf_cache -->
                <div class="alert alert-danger">当前 nginx.conf 中未设置 lua_shared_dict easy_waf_cache ?m;</div>
                <% else %>
                <!-- 设置有 easy_waf_cc_dict,展示信息 -->
                <p class="small text-muted">** 可根据实际使用情况调整设置容量。</p>
                <p class="small text-muted">** easy_waf_cache <span class="text-danger">请确保"可用空间"有富余容量。</span></p>
                <div class="row">
                  <div class="col-md-7 col-12">
                    <table class="table table-bordered table-sm m-0">
                      <tbody>
                        <tr>
                          <td class="col-name">配置容量</td>
                          <td class="col-value"><%- easy_waf_cache.capacity %></td>
                        </tr>
                        <tr>
                          <td class="col-name">当前可用空间</td>
                          <td class="col-value"><%- easy_waf_cache.free %></td>
                        </tr>
                        <tr>
                          <td class="col-name">当前使用key数量</td>
                          <td class="col-value"><%- easy_waf_cache.keys %></td>
                        </tr>
                      </tbody>
                    </table>
                  </div>
                </div>

                <div class="pb-2">
                  <p class="m-0">
                    <button type="button" id="btn_toggle_easy_waf_cache_kv" class="btn btn-primary" style="border-radius: 0">显示/隐藏所有 easy_waf_cache 键:值</button>
                  </p>
                  <div id="easy_waf_cache_kv_wrap" class="border border-primary p-3" style="display: none; max-height: 320px; overflow-x: hidden; overflow-y: auto">
                    <% for index, item in ipairs(easy_waf_cache.all_value) do %>
                    <div class="d-inline-block">
                      <p class="result-wrap">
                        <span class="prepend"><%- item[1] %></span>
                        <span class="result"><%- item[2] %></span>
                      </p>
                    </div>
                    <% end %>
                  </div>
                </div>
                <% end %>
              </blockquote>
            </div>
          </div>
        </div>
      </div>

      <div class="card p-md-3 my-3 shadow">
        <div class="card-body">
          <h2 class="text-primary card-title mb-3 mb-md-4">CC防护</h2>

          <div class="card-text">
            <h5 class="title-sub">cc_rate</h5>
            <div class="mx-md-3">
              <blockquote class="blockquote">
                <p>CC检测的请求频率 单位：请求次数N/M秒 ( 默认 100/60 : 60秒请求100次即触发CC攻击 )</p>

                <div>
                  WAF当前配置：
                  <div class="d-inline-block">
                    <p class="result-wrap">
                      <span class="prepend">cc_rate</span>
                      <span class="result"><%= config.cc_rate %></span>
                    </p>
                  </div>
                </div>
              </blockquote>
            </div>
          </div>

          <div class="card-text">
            <h5 class="title-sub">cc_ip_lock_time</h5>
            <div class="mx-md-3">
              <blockquote class="blockquote">
                <p>根据cc_rate检测到CC攻击时，封锁IP时长(单位:秒 如果为0则永久封锁)</p>

                <div>
                  WAF当前配置：
                  <div class="d-inline-block">
                    <p class="result-wrap">
                      <span class="prepend">cc_ip_lock_time</span>
                      <span class="result"><%= config.cc_ip_lock_time %></span>
                    </p>
                  </div>
                </div>
              </blockquote>
            </div>
          </div>

          <div class="card-text">
            <h5 class="title-sub">cc_dict_type</h5>
            <div class="mx-3">
              <blockquote class="blockquote">
                <p>CC防护使用的数据存储类型 ( <code>'redis'</code> / <code>'shared_dict'</code> )</p>

                <div>
                  WAF当前配置：
                  <div class="d-inline-block">
                    <p class="result-wrap">
                      <span class="prepend">cc_dict_type</span>
                      <span class="result"><%= config.cc_dict_type %></span>
                    </p>
                  </div>
                </div>
              </blockquote>
            </div>
          </div>

          <div class="card-text">
            <h5 class="title-sub">easy_waf_cc_dict</h5>
            <div class="mx-3">
              <blockquote class="blockquote">
                <p>如果 <code>cc_dict_type</code> 配置为 <code>shared_dict</code>，需要配置此项用于存储来访数据，从而计算访问频率。</p>
                <div>
                  配置方法：<code>nginx.conf http段</code> 添加
                  <div class="d-inline-block">
                    <p class="result-wrap">
                      <span class="prepend">lua_shared_dict</span>
                      <span class="result">easy_waf_cc_dict ?m;</span>
                    </p>
                  </div>
                </div>
                <% if not easy_waf_cc_dict then %>
                <!-- 未设置 easy_waf_cc_dict -->
                <div class="alert alert-danger">当前 nginx.conf 中未设置 lua_shared_dict easy_waf_cc_dict ?m;</div>
                <% else %>
                <!-- 设置有 easy_waf_cc_dict,展示信息 -->
                <p class="small text-muted">** 可根据实际使用情况调整设置容量。</p>
                <p class="small text-muted">** easy_waf_cc_dict 是根据来访 IP+URL 插入新值的，所以<span class="text-danger">请确保"可用空间"有富余容量。</span></p>
                <div class="row">
                  <div class="col-md-7 col-12">
                    <table class="table table-bordered table-sm">
                      <tbody>
                        <tr>
                          <td class="col-name">配置容量</td>
                          <td class="col-value"><%- easy_waf_cc_dict.capacity %></td>
                        </tr>
                        <tr>
                          <td class="col-name">当前可用空间</td>
                          <td class="col-value"><%- easy_waf_cc_dict.free %></td>
                        </tr>
                        <tr>
                          <td class="col-name">当前使用key数量</td>
                          <td class="col-value"><%- easy_waf_cc_dict.keys %></td>
                        </tr>
                      </tbody>
                    </table>
                  </div>
                </div>
                <% end %>
              </blockquote>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="footer p-1 fixed-bottom d-flex align-items-stretch justify-content-center">
      <!-- <div class="container-lg my-0"> -->
        <p>easy_ngx_waf by chleniang@163.com</p>
      <!-- </div> -->
    </div>
    <script>
      var btn_toggle_easy_waf_cache = document.getElementById("btn_toggle_easy_waf_cache_kv")
      var easy_waf_cache_kv_wrap = document.getElementById("easy_waf_cache_kv_wrap")
      btn_toggle_easy_waf_cache.onclick = function () {
        easy_waf_cache_kv_wrap.style.display = easy_waf_cache_kv_wrap.style.display == "none" ? "block" : "none"
      }
    </script>
  </body>
</html>
